#pragma once

struct PROCCB;
struct THRECB;
struct STREAM;
struct THRSTK;
struct MESSAGE;
struct HOOK_MSG;




typedef struct PROCCB _pcb;
typedef struct THRECB _tcb;
//typedef struct STREAM _str;

typedef struct MESSAGE _msg;
typedef struct HOOK_MSG _hook;


#include <ring.h>
#include <list.h>
#include <IPC/streamIO.h>
#include "MC.h"
#include <length.h>
#include "Interpreter.h"
#include <mmuInit.h>
#include <Sync/OSMsg.h>
#include <Sync/Delegate.h>

struct PROCCB
{
  //	unsigned long pID;//if the highest set is 1, it's a drive process; otherwise , it's not
  _ptlong flPage; 	//first level page
  _ptlong  entry; 	//programme entrance
  _ptlong _heap_start;	//memory start
  struct MESSAGE* msgbox;		
  _mlock msgboxLocker;
  struct HOOK_MSG* hooks;
  _mlock hooksLocker;
  _mch mhandle; 		//heap handle
  _hfptlong sharemem;		//the whole number
  _hfptlong left_sharemem;	//left number
  _hfptlong thrnum;		//the whole number
  _hfptlong left_thrnum;	//left number
  struct THRECB* mthread;		//main thread
  slnode* lockedmemory;
  slnode* streams;
  _mlock streamsLock;
  slnode* libmemory;
  slnode* hwdds;
  _fstr root;
} __attribute__((packed));

struct THRECB
{
  //	unsigned long tID;
  struct PROCCB* pPro;
  _stk stack;		//this is the using register
  _ptlong* stackPoint;	//this is the stack
  _ptlong* text;
  //	unsigned int* init_argv;	//init_argv[0] would be the flpage
  slnode* streams;		//you need to release them when ending!!
  _dlg delegates;
  _mlock delegatesLocker;
} __attribute__((packed));

struct MESSAGE
{
  struct THRECB* from;
  unsigned long mark;     //the mark of arg
  unsigned long* argv; //args
  unsigned long args;
  struct MESSAGE* next;	
} __attribute__((packed));

struct HOOK_MSG
{
  struct PROCCB* from;
  unsigned long mark;
  void (*fun)(struct THRECB*,_ptlong,_ptlong*,_ptlong);  
  //fun(_pcb* from,unsigned long mark,unsigned long* argv,unsigned long args);

  struct HOOK_MSG* next;
} __attribute__((packed));


typedef struct _ti_header_
{
  unsigned int image_size;
  unsigned int load_addr;
}ti_h;


#define SCHEDULE_DEFAULT		(0)
#define SCHEDULE_MUTEX			(1)
#define SCHEDULE_END			(2)
#define SCHEDULE_PROCESS_END		(3)

  inline int KernelSchedule(_ptlong mark);
  inline _tcb* BuildThread(_pcb* pro,_ptlong Function);
  inline _tcb* ArgvThread(_tcb* thr,_ptlong* argvs,_ptlong args);
  inline _tcb* RunThread(_tcb* thr);
  inline _tcb* KillThread(_tcb* thr);
  inline int KillProcess(_pcb* pro);

#ifndef OSPROC_CPP
extern volatile ring* run;
#endif
#define NOW				(((_tcb*)(run->content))->pPro)
#define NOWT				((_tcb*)(run->content))
#define ROOT 				(NOW->root)

